package fileIO;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;

public class IOUtil {

	public static void main(String[] args) throws IOException {
		// copyTest();
		// copyTest1();
		// encriptTest();
		testDirCopy();
		// test();
	}

	private static void test() {
		File d = new File("/home/tarena/Desktop");
		File d1 = new File("/home/tarena/Desktop/2");
		System.out.println(d.getName());
		System.out.println(d1.getName());
		System.out.println(d1.getAbsolutePath().substring(
				d.getAbsolutePath().length()));
	}

	private static void testDirCopy() throws IOException {
		File d = new File("/home/tarena/Desktop/1");
		String s = "utf-8";
		File d1 = new File("/home/tarena/Desktop/2");
		String s1 = "gbk";
		dirCopy(d, d1, s, s1);
	}

	private static void dirCopy(File fromDir, File toDir, String fromCharset,
			String toCharset) throws IOException {
		File[] files = fromDir.listFiles();
		toDir.mkdirs();
		for (int i = 0; i < files.length; i++) {
			if (files[i].isDirectory()) {
				dirCopy(files[i], new File(toDir + "/" + files[i].getName()),
						fromCharset, toCharset);
			} else {
				BufferedReader in = new BufferedReader(new InputStreamReader(
						new FileInputStream(files[i]), fromCharset));
				PrintWriter out = new PrintWriter(new BufferedWriter(
						new OutputStreamWriter(new FileOutputStream(new File(
								toDir, files[i].getName())), toCharset)));
				String s;
				while ((s = in.readLine()) != null) {
					out.println(s);
				}
				in.close();
				out.close();
			}

		}
	}

	private static void encriptTest() throws IOException {
		encript(new File("/home/tarena/Desktop/2"), new File(
				"/home/tarena/Desktop/3"));
	}

	private static void encript(File from, File to) throws IOException {
		BufferedInputStream in = new BufferedInputStream(new FileInputStream(
				from));
		BufferedOutputStream out = new BufferedOutputStream(
				new FileOutputStream(to));
		int b;
		while ((b = in.read()) != -1) {
			b = encriptByte(b);
			out.write(b);
		}
		in.close();
		out.close();
	}

	private static int encriptByte(int b) {
		return b ^ 0xff;// ~b
	}

	private static void decript(File from, File to) throws IOException {
		encript(from, to);
	}

	private static void copyTest1() throws UnsupportedEncodingException,
			IOException {
		File f1 = new File("/home/tarena/Desktop/1.txt");
		String code1 = "utf-8";
		File f2 = new File("/home/tarena/Desktop/2.txt");
		String code2 = "gbk";
		copy(f1, code1, f2, code2);
	}

	private static void copy(File from, String codeFrom, File to, String codeTo)
			throws UnsupportedEncodingException, IOException {
		InputStreamReader in = new InputStreamReader(new FileInputStream(from),
				codeFrom);
		OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(
				to, true), codeTo);
		char[] buf = new char[1024];
		int n;
		while ((n = in.read(buf)) != -1) {
			out.write(buf, 0, n);
		}
		in.close();
		out.close();
	}

	private static void copyTest() throws IOException {
		File f1 = new File("/home/tarena/Desktop/1.jpg");
		File f2 = new File("/home/tarena/Desktop/2.jpg");
		copy(f1, f2);
	}

	public static void copy(File from, File to) throws IOException {
		FileInputStream in = new FileInputStream(from);
		FileOutputStream out = new FileOutputStream(to);
		// buff=1024/2048/4096/8192，一次读写多个字节，减少磁盘读写更换磁道的次数，提高效率
		byte[] buf = new byte[1024];
		int n;// 读到的字节个数，读完了得到－1
		while ((n = in.read(buf)) != -1) {
			out.write(buf, 0, n);// 读进多少字节，写出多少字节
		}
		out.flush();// out.write(buf, 0, n);方法需要flush吗
		out.close();
		in.close();
	}

	public static File[] findByFilter(File dir, FileFilter filter) {
		File[] files = dir.listFiles();
		if (files == null || files.length == 0) {
			return new File[0];// 防止调用后方法后，使用返回值出现空指针异常
		}
		ArrayList<File> list = new ArrayList<File>();
		for (File file : files) {
			if (file.isFile()) {
				if (filter.accept(file)) {// 用过滤器判断文件是否符合条件
					list.add(file);
				}
			} else {
				File[] arr = findByFilter(file, filter);
				Collections.addAll(list, arr);
			}
		}
		return list.toArray(new File[0]);// 主要是给定类型，0无所谓
	}

	/**
	 * 根据文件名的特征查找文件
	 * 
	 * @param dir
	 * @param pattern
	 * @return
	 */
	public static File[] findByRegex(File dir, String pattern) {// ".*\\.java$"查找java文件
		File[] files = dir.listFiles();
		if (files == null || files.length == 0) {
			return new File[0];// 防止调用后方法后，使用返回值出现空指针异常
		}
		ArrayList<File> list = new ArrayList<File>();
		for (File file : files) {
			if (file.isFile()) {
				if (file.getName().matches(pattern)) {
					list.add(file);
				}
			} else {
				File[] arr = findByRegex(file, pattern);
				Collections.addAll(list, arr);
			}
		}
		return list.toArray(new File[0]);// 主要是给定类型，0无所谓
	}

	public static long dirLength(File dir) {
		File[] files = dir.listFiles();
		// files==null,可能没有访问权限
		if (files == null || files.length == 0) {
			return 0;
		}
		long size = 0;// size是字节数，应该判断返回值的单位
		for (File file : files) {
			if (file.isFile())
				size += file.length();
			else
				// 递归调用，求子目录的大小，需要判断操作系统，若是lunix，要加4096
				size += 4096 + dirLength(file);
		}
		return size;
	}

	/*
	 * 应该把能删的都删掉再返回，并指出哪些文件或者目录不能删除
	 */
	public static boolean deleteDir(File dir) {
		File[] files = dir.listFiles();
		// files==null,可能没有访问权限
		if (files == null || files.length == 0) {
			return dir.delete();
		}
		for (File file : files) {
			if (file.isFile()) {
				// 文件数组，把所有不能删除的文件包括进去
				if (!file.delete()) {
					// System.out.println(file.getName());
					return false;
				}
			} else {
				// 递归调用，删除子目录
				if (!deleteDir(file)) {
					return false;
				}
			}
		}
		return dir.delete();
	}
}
